<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us" lang="en-us">
<head>
  <link href="//gmpg.org/xfn/11" rel="profile">
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <meta name="generator" content="Hugo 0.68.3" />

  
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <title>排行榜逻辑 &middot; 我的博客</title>

  
  <link type="text/css" rel="stylesheet" href="/my_technology_blog/css/print.css" media="print">
  <link type="text/css" rel="stylesheet" href="/my_technology_blog/css/poole.css">
  <link type="text/css" rel="stylesheet" href="/my_technology_blog/css/syntax.css">
  <link type="text/css" rel="stylesheet" href="/my_technology_blog/css/hyde.css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Abril+Fatface|PT+Sans:400,400i,700">


  
  <link rel="apple-touch-icon-precomposed" sizes="144x144" href="/apple-touch-icon-144-precomposed.png">
  <link rel="shortcut icon" href="/favicon.png">

  
  
</head>

  <body class="theme-base-0b ">
  <aside class="sidebar">
  <div class="container sidebar-sticky">
    <div class="sidebar-about">
      <a href="/my_technology_blog/"><h1>我的博客</h1></a>
      <p class="lead">
       杨博的博客 
      </p>
    </div>

    <nav>
      <ul class="sidebar-nav">
        <li><a href="/my_technology_blog/">Home</a> </li>
        
      </ul>
    </nav>

    <p>&copy; 2021. All rights reserved. </p>
  </div>
</aside>

    <main class="content container">
    <div class="post">
  <h1>排行榜逻辑</h1>
  <time datetime=2020-04-08T15:43:26&#43;0800 class="post-date">Wed, Apr 8, 2020</time>
  <p>设想在一个游戏中，有上百万的玩家数据，如果现在需要你根据玩家的经验值整理一个前20名的排行榜，你会怎么做呢？
一般的做法是写一条类似下面这条sql语句的方式来获取</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python">select <span style="color:#f92672">*</span> <span style="color:#f92672">from</span> game_socre order by score desc limit <span style="color:#ae81ff">0</span>,<span style="color:#ae81ff">20</span>
</code></pre></div><p>实现这个功能主要用到的redis数据类型是redis的有序集合zset。zset 是set 类型的一个扩展,比原有的类型多了一个顺序属性.此属性在每次插入数据时会自动调整顺序值,保证value值按照一定顺序连续排列。</p>
<p>主要的实现思路是：
1、在一个新的玩家参与到游戏中时，在redis中的zset中新增一条记录（记录内容看具体的需求）score为0
2、当玩家的经验值发生变化时，修改该玩家的score值
3、使用redis的ZREVRANGE方法获取排行榜</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#75715e">#课程点击数统计</span>
<span style="color:#66d9ef">def</span> <span style="color:#a6e22e">course_click</span>(request):

    cid <span style="color:#f92672">=</span> request<span style="color:#f92672">.</span>GET<span style="color:#f92672">.</span>get(<span style="color:#e6db74">&#39;cid&#39;</span>)

    <span style="color:#75715e">#使用redis有序集合来记录</span>

    r<span style="color:#f92672">.</span>zincrby(<span style="color:#e6db74">&#39;course-click&#39;</span>,<span style="color:#ae81ff">1</span>,int(cid))

    res <span style="color:#f92672">=</span> {}
    res[<span style="color:#e6db74">&#39;code&#39;</span>] <span style="color:#f92672">=</span> <span style="color:#ae81ff">200</span>
    res[<span style="color:#e6db74">&#39;message&#39;</span>] <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;页面访问成功&#39;</span>

    <span style="color:#66d9ef">return</span> HttpResponse(json<span style="color:#f92672">.</span>dumps(res,ensure_ascii<span style="color:#f92672">=</span>False),content_type<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;application/json&#39;</span>)

<span style="color:#75715e">#获取排行榜前n位的数据</span>
<span style="color:#66d9ef">def</span> <span style="color:#a6e22e">get_top_n_users</span>(num):

    <span style="color:#75715e">#获取所有有序集合元素 进行切片操作</span>
    course_clicks <span style="color:#f92672">=</span> r<span style="color:#f92672">.</span>zrevrange(<span style="color:#e6db74">&#39;course-click&#39;</span>,<span style="color:#ae81ff">0</span>,<span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>,withscores<span style="color:#f92672">=</span>True)[:num]

    <span style="color:#75715e">#和mysql联动</span>
    course <span style="color:#f92672">=</span> Course<span style="color:#f92672">.</span>objects<span style="color:#f92672">.</span>in_bulk([int(item[<span style="color:#ae81ff">0</span>]) <span style="color:#66d9ef">for</span> item <span style="color:#f92672">in</span> course_clicks])

    <span style="color:#75715e">#将点击数和mysql结果集结合</span>
    res <span style="color:#f92672">=</span> []
    <span style="color:#75715e">#遍历</span>
    <span style="color:#66d9ef">for</span> item <span style="color:#f92672">in</span> course_clicks:

        <span style="color:#66d9ef">try</span>:
            res<span style="color:#f92672">.</span>append({int(item[<span style="color:#ae81ff">1</span>]):course[int(item[<span style="color:#ae81ff">0</span>])]})
        <span style="color:#66d9ef">except</span> <span style="color:#a6e22e">Exception</span> <span style="color:#66d9ef">as</span> e:
            <span style="color:#66d9ef">print</span>(str(e))
            <span style="color:#66d9ef">pass</span>
    <span style="color:#66d9ef">return</span> res

<span style="color:#75715e">#获取排行榜真实数据</span>
<span style="color:#66d9ef">def</span> <span style="color:#a6e22e">get_course_list</span>(request):

    <span style="color:#75715e">#调用数据</span>
    get_course <span style="color:#f92672">=</span> get_top_n_users(<span style="color:#ae81ff">3</span>)

    res <span style="color:#f92672">=</span> []

    <span style="color:#75715e">#拼装json</span>
    <span style="color:#66d9ef">for</span> dic <span style="color:#f92672">in</span> get_course:
        <span style="color:#66d9ef">for</span> k,v <span style="color:#f92672">in</span> dic<span style="color:#f92672">.</span>items():
            <span style="color:#75715e">#序列化</span>
            data <span style="color:#f92672">=</span> CourseSer(v)<span style="color:#f92672">.</span>data
            <span style="color:#75715e">#增加字段</span>
            data[<span style="color:#e6db74">&#39;click_number&#39;</span>] <span style="color:#f92672">=</span> k
            res<span style="color:#f92672">.</span>append(data)
    
    <span style="color:#66d9ef">return</span> HttpResponse(json<span style="color:#f92672">.</span>dumps(res,ensure_ascii<span style="color:#f92672">=</span>False),content_type<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;application/json&#39;</span>)
</code></pre></div>
</div>


    </main>

    
  </body>
</html>
